package  
{
	import as3isolib.display.primitive.IsoBox;
	import as3isolib.display.primitive.IsoHexBox;
	import as3isolib.display.primitive.IsoPolygon;
	import as3isolib.display.primitive.IsoPrimitive;
	import as3isolib.geom.IsoMath;
	import as3isolib.geom.Pt;
	import as3isolib.graphics.IFill;
	import as3isolib.graphics.Stroke;
	import com.smartfoxserver.v2.entities.User;
	import com.smartfoxserver.v2.entities.variables.SFSUserVariable;
	import flash.display.Sprite;
	import flash.text.TextField;
	/**
	 * ...
	 * @author Bryan Keiren & Sander van Katwijk
	 */
	public class Player
	{
		static protected var m_PlayerList:Vector.<Player> = new Vector.<Player>;
		static protected function registerPlayer(a_Player:Player):void		{	m_PlayerList.push(a_Player); Engine.printf("Number of players: " + m_PlayerList.length);	}
		static protected function unregisterPlayer(a_Player:Player):void	{	m_PlayerList.splice(m_PlayerList.indexOf(a_Player), 1); Engine.printf("Number of players: " + m_PlayerList.length);	}
		static public function getPlayers():Vector.<Player>					{	return m_PlayerList;									}
		static public function getPlayerByName(a_Name:String):Player		{	for each (var plyr:Player in m_PlayerList)
																				{	if (plyr.getName() == a_Name)	return plyr;	}
																				return null;											}
		static public function getPlayerByID(a_ID:int):Player				{	for each(var plyr:Player in m_PlayerList)
																				{	if (plyr.ID == a_ID)	return plyr;	}
																				return null;										 }
		
		static protected var m_CurPlayerID:int = 0;
		public var ID:int;
		
		protected var m_Name:String = "";
		protected var m_IsoHexBox:IsoHexBox;
		
		protected var m_Pos:Vector2 = null;
		protected var m_TargetPos:Vector2 = null;
		protected var m_NamePt:Pt = new Pt();
		
		protected var m_VisionRadius:Number = Globals.Cell_Size * 4;
		
		protected var m_NameTextfield:TextField = new TextField();
		
		public function setTargetPosX(a_X:int):void	{	m_TargetPos.x = a_X;	/*setTargetPos(m_TargetPos);*/	}
		public function setTargetPosY(a_Y:int):void	{	m_TargetPos.y = a_Y;	/*setTargetPos(m_TargetPos);*/	}
		public function setTargetPos(a_Pos:Vector2):void
		{
			// If more is added here, uncomment the call in setTargetPosX/Y.
			m_TargetPos = a_Pos;
			//Engine.printf("Player " + m_Name + " setting target to [" + a_Pos.x + ", " + a_Pos.y + "]");
		}
		
		public function getUser():User
		{
			if (Globals.Current_Game_Room != null)
			{
				return Globals.Current_Game_Room.getUserByName(m_Name);
			}
			return null;
		}
		
		public function setPosX(a_X:int):void	{	m_Pos.x = a_X; setPos(m_Pos);	}
		public function setPosY(a_Y:int):void	{	m_Pos.y = a_Y; setPos(m_Pos);	}
		public function setPos(a_Pos:Vector2):void
		{
			m_Pos = a_Pos;
			m_IsoHexBox.moveTo(a_Pos.x - m_IsoHexBox.width / 2, a_Pos.y - m_IsoHexBox.length / 2, 5);
		}
		
		static public function destroyAllExternalPlayers():void
		{
			var off:int = 0;
			while (m_PlayerList.length > 1)
			{
				if (m_PlayerList[off].getName() != LocalPlayer.Get().getName())
				{
					m_PlayerList[off].destroy();
				}
				else
				{
					off++;
				}
			}
		}
		
		protected var m_Team:Team = null;
		
		// Speed in units/second
		protected var m_Speed:Number = 150;
		
		public function Player(a_Name:String, a_Pos:Vector2, a_Team:Team = null)
		{
			ID = m_CurPlayerID++;
			
			m_Name = a_Name;
			
			if (a_Team == null)
				m_Team = Team.getDefaultTeam();
			else
				m_Team = a_Team;
			m_Team.addPlayer(this);
			
			m_Pos = a_Pos;
			m_TargetPos = new Vector2(a_Pos.x, a_Pos.y);
			
			m_IsoHexBox = new IsoHexBox();
			m_IsoHexBox.setSize(Globals.Cell_Size, Globals.Cell_Size, 5);
			m_IsoHexBox.fill = m_Team.getFill();
			setPos(a_Pos);
			
			m_IsoHexBox.container.mouseEnabled = false;
			
			m_NameTextfield.text = a_Name;
			m_NameTextfield.setTextFormat(Globals.Text_Format_Consolas10_Centered);
			m_NameTextfield.selectable = false;
			m_NameTextfield.mouseEnabled = false;
			m_NameTextfield.visible = false;			
			
			Player.registerPlayer(this);
		}
		public function destroy():void
		{
			Engine.printf("Deleting player " + ID);
			unregisterPlayer(this);
			disable();
			delete this;
		}
		
		public function setTeam(a_Team:Team):void
		{
			if(m_Team)
				m_Team.removePlayer(this);
			a_Team.addPlayer(this);
			
			m_Team = a_Team;
		}
		
		public function showName(bool:Boolean):void	{ m_NameTextfield.visible = bool; }
		
		public function getTeam():Team					{	return m_Team;		}
		public function setName(a_Name:String):void		{	m_Name = a_Name; m_NameTextfield.text = m_Name; m_NameTextfield.setTextFormat(Globals.Text_Format_Consolas15_AlignLeft);	}
		public function getName():String				{	return m_Name;		}
		public function getPos():Vector2				{ 	return m_Pos;		}
		
		public function setVisible(bool:Boolean):void
		{
			m_IsoHexBox.container.visible = bool;
			m_NameTextfield.visible = bool;
		}
		
		public function setAlpha(alpha:Number):void
		{
			//Engine.printf("alpha: " + alpha);
			m_IsoHexBox.container.alpha = alpha;
			m_NameTextfield.alpha = alpha * 3;
		}
		
		public function logic():void
		{
			//if(Math.random() < 0.5)
			//	trace("IMMA MOVING MY BOX");
			//else
			//	trace("A");
						
			// Update the name tag.
			m_NamePt.x = m_Pos.x;
			m_NamePt.y = m_Pos.y;
			m_NamePt.z = -70;
			m_NamePt = IsoMath.isoToScreen(m_NamePt, false);
			m_NamePt.x += Engine.Get().stage.width / 2;
			m_NameTextfield.x = m_NamePt.x;
			m_NameTextfield.y = m_NamePt.y;
			
			//Engine.printf("Executing logic for player " + m_Name);
			
			var dist:Number;
			// If we're the local player...
			if (LocalPlayer.Get().getName() == m_Name)
			{	
				// Iterate over all other players and hide/show them according to whether they are within our vision radius.
				for each (var otherplayer:Player in Player.getPlayers())
				{
					if (otherplayer.getName() != m_Name)
					{
						dist = otherplayer.getPos().dist(m_Pos);
						if (dist <= m_VisionRadius)
						{
							otherplayer.setVisible(true);
							otherplayer.setAlpha(1 - ((dist / m_VisionRadius)));
						}
						else
						{
							otherplayer.setVisible(false);
						}
					}
				}
			}
			
			
			if (!m_TargetPos.equals(m_Pos))
			{
				var delta:Vector2 = m_TargetPos.subtractV(m_Pos);
				
				dist = delta.length();
				
				
				// If we're more than m_Speed units away
				if (dist > m_Speed * Globals.Delta_Time_S)
				{
					// Calculate normalized direction, and move m_Speed units that way.
					var rDist:Number = 1 / dist;
					var norm:Vector2 = delta.divideN(dist);
					//Engine.printf("normX " + norm.x + ", normY " + norm.y);
					
					// m_Speed is in units/second.
					m_Pos = m_Pos.addV(norm.multiplyN(m_Speed).multiplyN(Globals.Delta_Time_S));
				}
				else
				{
					// We're less than m_Speed away, so we're there.
					m_Pos = m_Pos.addV(delta);
					m_Pos.Set(m_TargetPos);
					m_IsoHexBox.moveTo(m_Pos.x, m_Pos.y, 0);
					
					// If we're the local player...
					if (LocalPlayer.Get().getName() == m_Name)
					{						
						LocalPlayer.Get().setPosSynched(m_Pos);
						/*
						var newVars:Array = [];
						newVars.push(new SFSUserVariable("pos_x", m_Pos.x));
						newVars.push(new SFSUserVariable("pos_y", m_Pos.y));
						MessageHandler.Get().sendSetUserVariablesRequest(newVars);
						*/
					}
				}
				setPos(m_Pos);
			//	trace("TO " + m_Pos.x + ", " + m_Pos.y);
			}
		}
		
		public function setTeamColor():void
		{
			m_IsoHexBox.fill = m_Team.getFill();
		}
		
		public function enable():void
		{
			Game.Get().getScene().addChild(m_IsoHexBox);
			Engine.Get().addChild(m_NameTextfield);
			m_NameTextfield.visible = true;
		}
		public function disable():void
		{
			Game.Get().getScene().removeChild(m_IsoHexBox);
			if (Engine.Get().contains(m_NameTextfield))
			{
				Engine.Get().removeChild(m_NameTextfield);
			}
		}
	}
}